﻿Option Strict On
Option Explicit On
Option Infer On

Imports System
Imports System.Linq
Imports System.Collections.Generic
Imports System.Xml.Linq
Imports GenDotNet.TemplateData
Imports GenDotNet.Task.Common
Imports GenDotNet.TemplateSupport.Strings
Imports <xmlns:orm="http://kadgen.com/KADORM.xsd">

Public MustInherit Class DotNetBase
   Inherits TemplateBase

   ' There is a distinction here.Things native to the 
   ' entity, such as its inheritance and generics are in 
   ' the class info. Things that have to do with this template
   ' are direct fields.  
   Private mObjectData As IObjectData
   Private mContextStack As New ContextStack
   Private mClassNamespace As NamespaceInfo
   Private mFileImports As ImportInfoCollection
   Private mId As Guid
   'Private mAttributes As AttributeInfoCollection
   'Private mModifiers As TypeModifiers
   'Private mCategory As TypeCategory


   Protected MustOverride Function GenerateContents() As String

   Protected Sub New(ByVal id As Guid)
      mId = id
      mFileImports = New ImportInfoCollection
      'mAttributes = New AttributeInfoCollection
      'Me.Category = TypeCategory.Class
   End Sub

   Protected Overrides Function SetUp() As Boolean
      ' FUTURE: I want to add a provider pattern here later, but for now I'm focusing on the inerface usage
      Me.mObjectData = ObjectDataFactory.Load(Me.BaseElement)
      Me.FileNamespace = New NamespaceInfo(Me.ObjectData.ClassNamespace, AddressOf GenerateContents)
   End Function

   Public Function OutputContents() As String
      Return Me.GenerateContents()
   End Function

   Public ReadOnly Property ObjectData() As IObjectData
      Get
         Return mObjectData
      End Get
   End Property

   Public Property ContextStack() As ContextStack
      Get
         Return mContextStack
      End Get
      Protected Set(ByVal value As ContextStack)
         mContextStack = value
      End Set
   End Property

   Public Property FileNamespace() As NamespaceInfo
      Get
         Return mClassNamespace
      End Get
      Set(ByVal value As NamespaceInfo)
         mClassNamespace = value
      End Set
   End Property

   Public ReadOnly Property FileImports() As ImportInfoCollection
      Get
         Return mFileImports
      End Get
   End Property

   Public ReadOnly Property Id() As Guid
      Get
         Return mId
      End Get
   End Property

   '   ''' <summary>
   '   ''' USE DISCOURAGED! Creates the text that outputs an appropriate exception. Provide in 
   '   ''' case the exception is not available at generation time. If possible, use the Type overload
   '   ''' for strong typing
   '   ''' </summary>
   '   ''' <param name="name"></param>
   '   ''' <param name="locationId"></param>
   '   ''' <param name="message"></param>
   '   ''' <returns></returns>
   '   ''' <remarks>Designed to fail at generated code compile time if the ExceptionFactory does not know about this type</remarks>
   '   Protected Function OutputException( _
   '            ByVal name As String, _
   '            ByVal locationId As Guid, _
   '            ByVal message As String) _
   '            As String
   '      Return _
   '<code>
   '   <%= Strings.throwString %> ExceptionFasctory.Create<%= name %>(<%= Strings.newString %> System.Guid(<%= ObjectData.Id.Add(Me.Id.Add(locationId)) %>))
   '</code>.Value
   '   End Function

   Public Function PushContext(ByVal classInfo As TypeInfo) As String
      Me.ContextStack.Push(classInfo)
      Return String.Empty
   End Function

   Public Function PopContext() As String
      Me.ContextStack.Pop()
      Return String.Empty
   End Function

   Public Function CurrentTypeInfo() As TypeInfo
      If mContextStack Is Nothing OrElse mContextStack.Count = 0 Then
         Return Nothing
      End If
      Return Me.mContextStack.Peek.TypeInfo
   End Function
End Class

Public Module DotNetBaseExtensions
   ' TODO: Move these to a better location
   <Runtime.CompilerServices.Extension()> _
   Public Function CriteriaParameters(ByVal criteria As ICriteriaData) As ParameterInfo()
      Return (From x In criteria.Criterions _
               Select New ParameterInfo() _
               With {.Name = x.Name, .NetType = x.NetType}).ToArray()
   End Function

   <Runtime.CompilerServices.Extension()> _
Public Function CriteriaArguments(ByVal criteria As ICriteriaData) As String
      Return _
<code>
   <%= (From x In criteria.Criterions Select x.Name).ConcatenateWithComma %>
</code>.Value
   End Function

   ''' <summary>
   ''' Creates the text that outputs an appropriate exception. 
   ''' </summary>
   ''' <remarks>Designed to fail at generated code compile time if the ExceptionFactory does not know about this type</remarks>
   <Runtime.CompilerServices.Extension()> _
Public Function OutputException( _
          ByVal base As DotNetBase, _
          ByVal objectData As IObjectData, _
          ByVal type As Type, _
          ByVal locationId As Guid, _
          ByVal message As String) _
          As String
      Return _
<code>
   <%= Strings.throwString %> ExceptionFasctory.Create<%= type.Name %>(<%= Strings.newString %> System.Guid("<%= objectData.Id.Add(base.Id.Add(locationId)) %>"))
</code>.Value
   End Function

End Module


Namespace VB
   Public Module DotNetBaseExtensions
      <Runtime.CompilerServices.Extension()> _
      Public Sub SetStrings( _
               ByVal base As DotNetBase)

         Strings.wrapString = " _" & Strings.crlf
         Strings.returnString = "Return"
         Strings.newString = "New"
         Strings.andAlsoString = "AndAlso"
         Strings.andString = "And"
         Strings.orElseString = "OrElse"
         Strings.orString = "Or"
         Strings.meString = "Me"
         Strings.trueString = "True"
         Strings.falseString = "False"
         Strings.notString = "Not"
         Strings.nullString = "Nothing"
         Strings.throwString = "Throw"
         Strings.baseString = "MyBase"
         Strings.getTypeString = "GetType"
         Strings.semiColonString = ""

      End Sub

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputFileName(ByVal partialName As String) As String
         Return partialName & ".vb"
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputFile(ByVal base As DotNetBase) As String
         Return _
   <code>
      <%= base.FileImports.Output %>
      <%= If(base.FileNamespace Is Nothing, base.OutputContents(), base.FileNamespace.Output()) %>
   </code>.Value
      End Function

      <Runtime.CompilerServices.Extension()> _
     Public Function CleanOutput(ByVal out As String) As String
         Return out.Replace("[", "(").Replace("]", ")")
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputNew(ByVal base As DotNetBase) As String
      '   Return "New"
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputNew(ByVal base As DotNetBase, ByVal typeInfo As NetTypeInfo) As String
      '   Return "New " & typeInfo.Output & "()"
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function WithSemiColons(ByVal code As IEnumerable(Of XElement)) As String
         Return code.Value
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function WithSemiColons(ByVal code As XElement) As String
         Return code.Value
      End Function

#Region "Output Convenience Functions - This region should remain identical in C# and VB to facilitate copying!"

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputClass( _
               ByVal template As DotNetBase, _
               ByVal classInfo As TypeInfo, _
               ByVal del As EmptyDelegate) _
               As String
         Return _
<code>
   <%= template.PushContext(classInfo) %>
   <%= classInfo.OutputOpening() %>
   <%= del.Invoke() %>
   <%= classInfo.OutputClose() %>
   <%= template.PopContext() %>
</code>.Value
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputClass( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As TypeModifiers, _
      '         ByVal attributes As StandardAttributes, _
      '         ByVal del As EmptyDelegate) _
      '         As String
      '   Dim info = New TypeInfo(name, scope, TypeCategory.Class, modifiers)
      '   info.Attributes.Add(attributes)
      '   Return template.OutputClass(info, del)
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputRegion( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal del As EmptyDelegate) _
               As String
         Return New RegionInfo(name, del).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputComment( _
               ByVal template As DotNetBase, _
               ByVal comment As String) _
               As String
         Return New CommentInfo(comment).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputXmlComment( _
               ByVal template As DotNetBase, _
               ByVal comment As String) _
               As String
         Return New CommentInfo(comment, True).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputConstructor( _
               ByVal template As DotNetBase, _
               ByVal scope As Scope, _
               ByVal del As EmptyDelegate, _
               ByVal ParamArray parameters() As ParameterInfo) _
               As String
         Return New ConstructorInfo(template.CurrentTypeInfo, scope, del, parameters).Output()
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputSub( _
      '          ByVal template As DotNetBase, _
      '          ByVal name As String, _
      '          ByVal scope As Scope, _
      '          ByVal del As EmptyDelegate, _
      '          ByVal ParamArray parameters() As ParameterInfo) _
      '          As String
      '   Return New SubInfo(name, template.CurrentTypeInfo, scope, Nothing, del, parameters).Output()
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputSub( _
              ByVal template As DotNetBase, _
              ByVal name As String, _
              ByVal scope As Scope, _
              ByVal modifiers As MemberModifiers, _
              ByVal del As EmptyDelegate, _
              ByVal ParamArray parameters() As ParameterInfo) _
              As String
         Return New SubInfo(name, template.CurrentTypeInfo, scope, modifiers, del, parameters).Output()
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputFunction( _
              ByVal template As DotNetBase, _
              ByVal name As String, _
              ByVal scope As Scope, _
              ByVal modifiers As MemberModifiers, _
              ByVal returnType As NetTypeInfo, _
              ByVal del As EmptyDelegate, _
              ByVal ParamArray parameters() As ParameterInfo) _
              As String
         Return New FunctionInfo(name, template.CurrentTypeInfo, scope, modifiers, returnType, del, parameters).Output()
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputFunction( _
      '        ByVal template As DotNetBase, _
      '        ByVal name As String, _
      '        ByVal scope As Scope, _
      '        ByVal returnType As NetTypeInfo, _
      '        ByVal del As EmptyDelegate, _
      '        ByVal ParamArray parameters() As ParameterInfo) _
      '        As String
      '   Return New FunctionInfo(name, template.CurrentTypeInfo, scope, Nothing, returnType, del, parameters).Output()
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputFunction( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As MemberModifiers, _
      '         ByVal returnType As String, _
      '         ByVal del As EmptyDelegate, _
      '         ByVal propertyData As IPropertyData, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New FunctionInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '            New NetTypeInfo(returnType), del, parameters).Output()
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputFunction( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As MemberModifiers, _
      '         ByVal returnType As String, _
      '         ByVal del As EmptyDelegate, _
      '         ByVal childData As IChildData, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New FunctionInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '            New NetTypeInfo(returnType), del, parameters).Output()
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputFunction( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As MemberModifiers, _
      '         ByVal returnType As String, _
      '         ByVal del As EmptyDelegate, _
      '         ByVal criteriaData As ICriteriaData, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New FunctionInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '            New NetTypeInfo(returnType), del, parameters).Output()
      'End Function

      Public Function OutputFunctionCall( _
               ByVal functionName As String, _
               ByVal generics As GenericInfoCollection, _
               ByVal ParamArray params() As ParameterInfo) _
               As String
         Return _
   <code>
      <%= functionName.WithSpace %><%= generics.Output %>()<%= nws %>
   </code>.Value
      End Function

      Public Function OutputFunctionCall( _
               ByVal functionName As String, _
               ByVal generic As String, _
               ByVal ParamArray params() As ParameterInfo) _
               As String
         Return _
   <code>
      <%= functionName.WithSpace %><%= (New GenericInfo(generic)).Output %>()<%= nws %>
   </code>.Value
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal returnType As NetTypeInfo, _
      '         ByVal isReadOnly As Boolean, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New PropertyInfo(name, template.CurrentTypeInfo, scope, _
      '             returnType, isReadOnly, Nothing, parameters).Output(template.ObjectData)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '          ByVal template As DotNetBase, _
      '          ByVal name As String, _
      '          ByVal scope As Scope, _
      '          ByVal modifiers As MemberModifiers, _
      '          ByVal returnType As NetTypeInfo, _
      '          ByVal isReadOnly As Boolean, _
      '          ByVal ParamArray parameters() As ParameterInfo) _
      '          As String
      '   Return New PropertyInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '             returnType, isReadOnly, Nothing, Nothing, parameters).Output(template.ObjectData)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal returnType As NetTypeInfo, _
      '         ByVal isReadOnly As Boolean, _
      '         ByVal getDelegate As EmptyDelegate, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New PropertyInfo(name, template.CurrentTypeInfo, scope, _
      '             returnType, isReadOnly, getDelegate, parameters).Output(template.ObjectData)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As MemberModifiers, _
      '         ByVal returnType As NetTypeInfo, _
      '         ByVal isReadOnly As Boolean, _
      '         ByVal getDelegate As EmptyDelegate, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New PropertyInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '             returnType, isReadOnly, getDelegate, Nothing, parameters).Output(template.ObjectData)
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputProperty( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal scope As Scope, _
               ByVal modifiers As MemberModifiers, _
               ByVal returnType As NetTypeInfo, _
               ByVal isReadOnly As Boolean, _
               ByVal getDelegate As EmptyDelegate, _
               ByVal setDelegate As EmptyDelegate, _
               ByVal ParamArray parameters() As ParameterInfo) _
               As String
         Return New PropertyInfo(name, template.CurrentTypeInfo, scope, modifiers, _
                   returnType, isReadOnly, getDelegate, setDelegate, parameters).Output(template.ObjectData)
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '         ByVal template As DotNetBase, _
      '         ByVal prop As IPropertyData, _
      '         ByVal scope As Scope, _
      '         ByVal getDelegate As EmptyDelegate, _
      '         ByVal setDelegate As EmptyDelegate, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New PropertyInfo(prop.Name, template.CurrentTypeInfo, scope, MemberModifiers.None, _
      '             prop.NetType, False, getDelegate, setDelegate, parameters).Output(template.ObjectData)
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputProperty( _
               ByVal template As DotNetBase, _
               ByVal prop As IPropertyData, _
               ByVal scope As Scope, _
               ByVal modifiers As MemberModifiers, _
               ByVal isReadOnly As Boolean, _
               ByVal getDelegate As EmptyDelegate, _
               ByVal setDelegate As EmptyDelegate, _
               ByVal ParamArray parameters() As ParameterInfo) _
               As String
         Return New PropertyInfo(prop.Name, template.CurrentTypeInfo, scope, modifiers, _
                   prop.NetType, isReadOnly, getDelegate, setDelegate, parameters).Output(template.ObjectData)
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputVariable( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo) _
               As String
         Return New VariableInfo(name, True, netType).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputVariable( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo, _
               ByVal setNew As Boolean) _
               As String
         Return New VariableInfo(name, True, netType, setNew).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputVariable( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo, _
               ByVal defaultValue As String) _
               As String
         ' Assume private for feilds
         Return New VariableInfo(name, True, netType, defaultValue).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo) _
               As String
         Return New VariableInfo(name, Scope.Private, netType).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo, _
               ByVal setNew As Boolean) _
               As String
         Return New VariableInfo(name, Scope.Private, netType, setNew).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo, _
               ByVal defaultValue As String) _
               As String
         ' Assume private for feilds
         Return New VariableInfo(name, Scope.Private, netType, defaultValue).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
         ByVal prop As IPropertyData) _
         As String
         ' Assume private for feilds
         Return New VariableInfo(prop.Name, Scope.Private, prop.NetType, prop.DefaultValue).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
         ByVal child As IChildData) _
         As String
         ' Assume private for feilds
         Return New VariableInfo(child.Name, Scope.Private, StandardNetType.Unknown, True).Output
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputConditional( _
      '         ByVal template As DotNetBase, _
      '         ByVal expression As String, _
      '         ByVal contents As EmptyDelegate, _
      '         Optional ByVal data As IBaseData = Nothing) _
      '         As String
      '   Return New ConditionalInfo(expression, contents).Output(data)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputForEach( _
      '         ByVal template As DotNetBase, _
      '         ByVal loopVariable As String, _
      '         ByVal loopIn As String, _
      '         ByVal contents As EmptyDelegate, _
      '         Optional ByVal data As IBaseData = Nothing) _
      '         As String
      '   Return New ForEachInfo(loopVariable, loopIn, contents).Output(data)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputForEach( _
      '         ByVal template As DotNetBase, _
      '         ByVal loopVariable As String, _
      '         ByVal loopIn As String, _
      '         ByVal netType As NetTypeInfo, _
      '         ByVal contents As EmptyDelegate, _
      '         Optional ByVal data As IBaseData = Nothing) _
      '         As String
      '   Return New ForEachInfo(loopVariable, loopIn, netType, contents).Output(data)
      'End Function
#End Region


   End Module

End Namespace

Namespace CSharp
   Public Module DotNetBaseExtensions
      <Runtime.CompilerServices.Extension()> _
      Public Sub SetStrings( _
                  ByVal base As DotNetBase)
         Strings.wrapString = " _" & Strings.crlf
         Strings.returnString = "return"
         Strings.newString = "new"
         Strings.andAlsoString = "&&"
         Strings.andString = "&"
         Strings.orElseString = "||"
         Strings.orString = "|"
         Strings.meString = "this"
         Strings.trueString = "true"
         Strings.falseString = "false"
         Strings.notString = "!"
         Strings.nullString = "null"
         Strings.throwString = "throw"
         Strings.baseString = "base"
         Strings.getTypeString = "typeof"
         Strings.semiColonString = ";"

      End Sub

      <Runtime.CompilerServices.Extension()> _
     Public Function OutputFileName(ByVal partialName As String) As String
         Return partialName & ".cs"
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputFile(ByVal base As DotNetBase) As String
         Return _
   <code>
      <%= base.FileImports.Output %>
      <%= If(base.FileNamespace Is Nothing, base.OutputContents(Nothing), base.FileNamespace.Output()) %>
   </code>.Value
      End Function

      <Runtime.CompilerServices.Extension()> _
     Public Function CleanOutput(ByVal out As String) As String
         out = out.Replace(" _", "")
         Dim lines = out.Split(Convert.ToChar(Microsoft.VisualBasic.ControlChars.Lf))
         Dim ret = String.Empty
         For Each line In lines
            Dim content = If(line.Contains("//"), line.SubstringBefore("//"), line)
            Dim comments = If(line.Contains("//"), line.SubstringAfter("//"), String.Empty)
            'content = AddSemis(content)
            content = FixCase(content)
            line = content & If(String.IsNullOrEmpty(comments), String.Empty, "//" & comments)
            ret &= line & Microsoft.VisualBasic.ControlChars.Lf
         Next
         Return ret
      End Function

      'Private Function AddSemis(ByVal content As String) As String
      '   Dim ret = String.Empty
      '   If String.IsNullOrEmpty(content) OrElse content.Trim.Length = 0 OrElse _
      '         (content.TrimStart.StartsWith("if (") Or _
      '          content.TrimStart.StartsWith("if(") Or _
      '          content.TrimStart.StartsWith("foreach (") Or _
      '          content.TrimStart.StartsWith("foreach(") Or _
      '          content.TrimStart.StartsWith("namespace ") Or _
      '          content.Trim = "{" Or content.Trim = "}" Or _
      '          content.Trim.EndsWith("_") Or _
      '          content.Trim.EndsWith("]")) Then
      '      ret &= content & Microsoft.VisualBasic.ControlChars.Lf
      '   Else
      '      If Not content.TrimEnd.EndsWith(";") Then
      '         ret &= content & ";" & Microsoft.VisualBasic.ControlChars.Lf
      '      End If
      '   End If
      '   Return ret
      'End Function

      Private Function FixCase(ByVal content As String) As String
         Dim ret = content
         ret = FixSpecificCase(ret, "New", "new", True, True)
         ret = FixSpecificCase(ret, "Return", "return", False, True)
         ret = FixSpecificCase(ret, "True", "true", True, False)
         ret = FixSpecificCase(ret, "False", "false", True, False)
         Return ret
      End Function

      Private Function FixSpecificCase( _
               ByVal ret As String, _
               ByVal badCase As String, _
               ByVal goodCase As String, _
               ByVal allowPreceding As Boolean, _
               ByVal forceTrailingSpace As Boolean) As String
         If ret.Contains(badCase) Then
            ' so it might need replacement, but we need to not replace in symbols
            Dim leading = ret.SubstringBefore(badCase)
            If leading.Trim.Length = 0 Then
               ret = ret.TrimStart
               If ret.StartsWith(badCase) Then
                  If ret.Length = badCase.Length OrElse " ),".Contains(ret.Substring(badCase.Length, 1)) Then
                     ret = goodCase & ret.Substring(badCase.Length)
                  End If
                  ret = leading & ret
               End If
            End If
            If ret.Contains(badCase) Then
               If allowPreceding Then
                  ret = ret.Replace(" " & badCase & " ", " " & goodCase & " ")
                  ret = ret.Replace("(" & badCase & " ", "(" & goodCase & " ")
                  ret = ret.Replace("," & badCase & " ", "," & goodCase & " ")
                  If Not forceTrailingSpace Then
                     ret = ret.Replace(" " & badCase & ")", " " & goodCase & ")")
                     ret = ret.Replace("(" & badCase & ")", "(" & goodCase & ")")
                     ret = ret.Replace("," & badCase & ")", "," & goodCase & ")")
                     ret = ret.Replace(" " & badCase & ",", " " & goodCase & ",")
                     ret = ret.Replace("(" & badCase & ",", "(" & goodCase & ",")
                     ret = ret.Replace("," & badCase & ",", "," & goodCase & ",")
                  End If
               End If
            End If
         End If
         Return ret
      End Function

      '<Runtime.CompilerServices.Extension()> _
      ' Public Function OutputNew(ByVal base As DotNetBase) As String
      '   Return "new"
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputNew(ByVal base As DotNetBase, ByVal typeInfo As NetTypeInfo) As String
      '   Return "new " & typeInfo.Output() & "()"
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function WithSemiColons(ByVal code As String) As String
         Dim lines = code.Split(Convert.ToChar(Microsoft.VisualBasic.ControlChars.Lf))
         Dim logicalLine = String.Empty
         Dim ret = String.Empty
         For Each line In lines
            logicalLine &= line
            If line.Trim.EndsWith("_") Then
               logicalLine &= crlf
            Else
               ret &= AddSemiIfNeeded(logicalLine)
               logicalLine = String.Empty
            End If
         Next
         Return ret
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function WithSemiColons(ByVal code As IEnumerable(Of XElement)) As String
         Return code.Value.WithSemiColons()
         'Dim s = code.Value
         'Dim lines = s.Split(Convert.ToChar(Microsoft.VisualBasic.ControlChars.Cr))
         'Dim ret = String.Empty
         'For Each line In lines
         '   ret &= AddSemiIfNeeded(line)
         'Next
         'Return ret
      End Function

      <Runtime.CompilerServices.Extension()> _
       Public Function WithSemiColons(ByVal code As XElement) As String
         Return code.Value.WithSemiColons()
         'Dim s = code.Value
         'Dim lines = s.Split(Convert.ToChar(Microsoft.VisualBasic.ControlChars.Lf))
         'Dim ret = String.Empty
         'For Each line In lines
         '   ret &= AddSemiIfNeeded(line)
         'Next
         'Return ret
      End Function

      Private Function AddSemiIfNeeded(ByVal line As String) As String
         Dim ret = String.Empty
         If String.IsNullOrEmpty(line) OrElse line.Trim.Length = 0 OrElse _
                  (line.TrimStart.StartsWith("if (") Or _
                   line.TrimStart.StartsWith("if(") Or _
                   line.TrimStart.StartsWith("foreach (") Or _
                   line.TrimStart.StartsWith("foreach(") Or _
                   line.Trim = "{" Or line.Trim = "}" Or _
                   line.Trim.EndsWith("_")) Then
            ret &= line & Microsoft.VisualBasic.ControlChars.Lf
         Else
            If Not line.TrimEnd.EndsWith(";") Then
               ret &= line & ";" & Microsoft.VisualBasic.ControlChars.Lf
            End If
         End If
         Return ret
      End Function

#Region "Output Convenience Functions - This region should remain identical in C# and VB to facilitate copying!"
      <Runtime.CompilerServices.Extension()> _
      Public Function OutputClass( _
               ByVal template As DotNetBase, _
               ByVal classInfo As TypeInfo, _
               ByVal del As EmptyDelegate) _
               As String
         Return _
<code>
   <%= template.PushContext(classInfo) %>
   <%= classInfo.OutputOpening() %>
   <%= del.Invoke() %>
   <%= classInfo.OutputClose() %>
   <%= template.PopContext() %>
</code>.Value
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputRegion( _
      '         ByVal template As DotNetBase, _
      '         ByVal del As EmptyDelegate) As String
      '   Return New RegionInfo(del).Output
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputRegion( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal del As EmptyDelegate) _
               As String
         Return New RegionInfo(name, del).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputComment( _
               ByVal template As DotNetBase, _
               ByVal comment As String) _
               As String
         Return New CommentInfo(comment).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputConstructor( _
               ByVal template As DotNetBase, _
               ByVal scope As Scope, _
               ByVal del As EmptyDelegate, _
               ByVal ParamArray parameters() As ParameterInfo) _
               As String
         Return New ConstructorInfo(template.CurrentTypeInfo, scope, del, parameters).Output()
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputSub( _
      '          ByVal template As DotNetBase, _
      '          ByVal name As String, _
      '          ByVal scope As Scope, _
      '          ByVal del As EmptyDelegate, _
      '          ByVal ParamArray parameters() As ParameterInfo) _
      '          As String
      '   Return New SubInfo(name, template.CurrentTypeInfo, scope, Nothing, del, parameters).Output()
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputSub( _
              ByVal template As DotNetBase, _
              ByVal name As String, _
              ByVal scope As Scope, _
              ByVal modifiers As MemberModifiers, _
              ByVal del As EmptyDelegate, _
              ByVal ParamArray parameters() As ParameterInfo) _
              As String
         Return New SubInfo(name, template.CurrentTypeInfo, scope, modifiers, del, parameters).Output()
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputFunction( _
              ByVal template As DotNetBase, _
              ByVal name As String, _
              ByVal scope As Scope, _
              ByVal modifiers As MemberModifiers, _
              ByVal returnType As NetTypeInfo, _
              ByVal del As EmptyDelegate, _
              ByVal ParamArray parameters() As ParameterInfo) _
              As String
         Return New FunctionInfo(name, template.CurrentTypeInfo, scope, modifiers, returnType, del, parameters).Output()
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputFunction( _
      '        ByVal template As DotNetBase, _
      '        ByVal name As String, _
      '        ByVal scope As Scope, _
      '        ByVal returnType As NetTypeInfo, _
      '        ByVal del As EmptyDelegate, _
      '        ByVal ParamArray parameters() As ParameterInfo) _
      '        As String
      '   Return New FunctionInfo(name, template.CurrentTypeInfo, scope, Nothing, returnType, del, parameters).Output()
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputFunction( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As MemberModifiers, _
      '         ByVal returnType As String, _
      '         ByVal del As EmptyDelegate, _
      '         ByVal propertyData As IPropertyData, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New FunctionInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '            New NetTypeInfo(returnType), del, parameters).Output()
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputFunction( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As MemberModifiers, _
      '         ByVal returnType As String, _
      '         ByVal del As EmptyDelegate, _
      '         ByVal childData As IChildData, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New FunctionInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '            New NetTypeInfo(returnType), del, parameters).Output()
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputFunction( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As MemberModifiers, _
      '         ByVal returnType As String, _
      '         ByVal del As EmptyDelegate, _
      '         ByVal criteriaData As ICriteriaData, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New FunctionInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '            New NetTypeInfo(returnType), del, parameters).Output()
      'End Function

      Public Function OutputFunctionCall( _
               ByVal functionName As String, _
               ByVal generics As GenericInfoCollection, _
               ByVal ParamArray params() As ParameterInfo) _
               As String
         Return _
   <code>
      <%= functionName.WithSpace %><%= generics.Output %>()<%= nws %>
   </code>.Value
      End Function

      Public Function OutputFunctionCall( _
               ByVal functionName As String, _
               ByVal generic As String, _
               ByVal ParamArray params() As ParameterInfo) _
               As String
         Return _
   <code>
      <%= functionName.WithSpace %><%= (New GenericInfo(generic)).Output %>()<%= nws %>
   </code>.Value
      End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal returnType As NetTypeInfo, _
      '         ByVal isReadOnly As Boolean, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New PropertyInfo(name, template.CurrentTypeInfo, scope, _
      '             returnType, isReadOnly, Nothing, parameters).Output(template.ObjectData)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '          ByVal template As DotNetBase, _
      '          ByVal name As String, _
      '          ByVal scope As Scope, _
      '          ByVal modifiers As MemberModifiers, _
      '          ByVal returnType As NetTypeInfo, _
      '          ByVal isReadOnly As Boolean, _
      '          ByVal ParamArray parameters() As ParameterInfo) _
      '          As String
      '   Return New PropertyInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '             returnType, isReadOnly, Nothing, Nothing, parameters).Output(template.ObjectData)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal returnType As NetTypeInfo, _
      '         ByVal isReadOnly As Boolean, _
      '         ByVal getDelegate As EmptyDelegate, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New PropertyInfo(name, template.CurrentTypeInfo, scope, _
      '             returnType, isReadOnly, getDelegate, parameters).Output(template.ObjectData)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputProperty( _
      '         ByVal template As DotNetBase, _
      '         ByVal name As String, _
      '         ByVal scope As Scope, _
      '         ByVal modifiers As MemberModifiers, _
      '         ByVal returnType As NetTypeInfo, _
      '         ByVal isReadOnly As Boolean, _
      '         ByVal getDelegate As EmptyDelegate, _
      '         ByVal ParamArray parameters() As ParameterInfo) _
      '         As String
      '   Return New PropertyInfo(name, template.CurrentTypeInfo, scope, modifiers, _
      '             returnType, isReadOnly, getDelegate, Nothing, parameters).Output(template.ObjectData)
      'End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputProperty( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal scope As Scope, _
               ByVal modifiers As MemberModifiers, _
               ByVal returnType As NetTypeInfo, _
               ByVal isReadOnly As Boolean, _
               ByVal getDelegate As EmptyDelegate, _
               ByVal setDelegate As EmptyDelegate, _
               ByVal ParamArray parameters() As ParameterInfo) _
               As String
         Return New PropertyInfo(name, template.CurrentTypeInfo, scope, modifiers, _
                   returnType, isReadOnly, getDelegate, setDelegate, parameters).Output(template.ObjectData)
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputProperty( _
             ByVal template As DotNetBase, _
             ByVal prop As IPropertyData, _
             ByVal scope As Scope, _
             ByVal modifiers As MemberModifiers, _
             ByVal isReadOnly As Boolean, _
             ByVal getDelegate As EmptyDelegate, _
             ByVal setDelegate As EmptyDelegate, _
             ByVal ParamArray parameters() As ParameterInfo) _
             As String
         Return New PropertyInfo(prop.Name, template.CurrentTypeInfo, scope, modifiers, _
                   prop.NetType, isReadOnly, getDelegate, setDelegate, parameters).Output(template.ObjectData)
      End Function

      <Runtime.CompilerServices.Extension()> _
        Public Function OutputVariable( _
                 ByVal template As DotNetBase, _
                 ByVal name As String, _
                 ByVal netType As NetTypeInfo) _
                 As String
         Return New VariableInfo(name, True, netType).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputVariable( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo, _
               ByVal setNew As Boolean) _
               As String
         Return New VariableInfo(name, True, netType, setNew).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputVariable( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo, _
               ByVal defaultValue As String) _
               As String
         ' Assume private for feilds
         Return New VariableInfo(name, True, netType, defaultValue).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo) _
               As String
         Return New VariableInfo(name, Scope.Private, netType).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo, _
               ByVal setNew As Boolean) _
               As String
         Return New VariableInfo(name, Scope.Private, netType, setNew).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
               ByVal template As DotNetBase, _
               ByVal name As String, _
               ByVal netType As NetTypeInfo, _
               ByVal defaultValue As String) _
               As String
         ' Assume private for feilds
         Return New VariableInfo(name, Scope.Private, netType, defaultValue).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
     Public Function OutputField( _
        ByVal prop As IPropertyData) _
        As String
         ' Assume private for feilds
         Return New VariableInfo(prop.Name, Scope.Private, prop.NetType, prop.DefaultValue).Output
      End Function

      <Runtime.CompilerServices.Extension()> _
      Public Function OutputField( _
         ByVal child As IChildData) _
         As String
         ' Assume private for feilds
         Return New VariableInfo(child.Name, Scope.Private, StandardNetType.Unknown, True).Output
      End Function

      '<Runtime.CompilerServices.Extension()> _
      ' Public Function OutputConditional( _
      '          ByVal template As DotNetBase, _
      '          ByVal expression As String, _
      '          ByVal contents As EmptyDelegate, _
      '          Optional ByVal data As IBaseData = Nothing) _
      '          As String
      '   Return New ConditionalInfo(expression, contents).Output(data)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputForEach( _
      '         ByVal template As DotNetBase, _
      '         ByVal loopVariable As String, _
      '         ByVal loopIn As String, _
      '         ByVal contents As EmptyDelegate, _
      '         Optional ByVal data As IBaseData = Nothing) _
      '         As String
      '   Return New ForEachInfo(loopVariable, loopIn, contents).Output(data)
      'End Function

      '<Runtime.CompilerServices.Extension()> _
      'Public Function OutputForEach( _
      '         ByVal template As DotNetBase, _
      '         ByVal loopVariable As String, _
      '         ByVal loopIn As String, _
      '         ByVal netType As NetTypeInfo, _
      '         ByVal contents As EmptyDelegate, _
      '         Optional ByVal data As IBaseData = Nothing) _
      '         As String
      '   Return New ForEachInfo(loopVariable, loopIn, netType, contents).Output(data)
      'End Function
#End Region

   End Module


End Namespace
